package SQL.scan;


import Metadata.attrSchema;
import Metadata.HeapfileInterface;
import heap.RID;
import heap.ResultField;
import heap.ResultRow;
import heap.ResultSchema;
import heap.Tuple;
import Transaction.Transaction;

public class TableScan implements Scan {
	/**
	 * tbl-ref ::= tbl-name
	 * @param dbName
	 * @param tblName
	 * @param tx
	 */
	public TableScan(String tblName,String dbName,Transaction tx) throws Exception {
		if(tblName == null){
			flag = true;
			return;
		}
		this.dbName = dbName;
		this.tblName = tblName;
		this.tx = tx;
		//get the Table relavent info from heap~~
		attrSchema[] catalog = HeapfileInterface.getTableInfo(dbName+"."+tblName, tx);
		this.schema = new ResultSchema();
		for(attrSchema cat : catalog){
			schema.add(new ResultField(tblName+"."+cat.attrName, cat.attrType.attrType, cat.attrLen));
		}
		s = HeapfileInterface.getTableIterator(dbName+"."+tblName, tx);
	}
	/**
	 * tbl-ref ::= tbl-name[AS alias] 
	 * @param dbName
	 * @param tblName
	 * @param alias
	 * @param tx
	 * @throws Exception
	 */
	public TableScan(String tblName,String dbName,String alias,Transaction tx) throws Exception {
		if(tblName == null){
			flag = true;
			return;
		}
		this.tblName = tblName;
		this.dbName = dbName;
		this.tx = tx;
		if(alias == null){
			alias = tblName;
		}
		attrSchema[] catalog= HeapfileInterface.getTableInfo(dbName+"."+tblName, tx);
		this.schema = new ResultSchema();
		for(attrSchema cat : catalog){
			schema.add(new ResultField(alias+"."+cat.attrName, cat.attrType.attrType,cat.attrLen));
		}
		s = HeapfileInterface.getTableIterator(dbName+"."+tblName, tx);
	}
//	/**
//	 * tbl-ref ::= (subquery) AS alias 
//	 * @param dbName
//	 * @param subquery
//	 * @param alias
//	 * @param tx
//	 * @throws Exception
//	 */
//	public TableScan(String dbName,SQL subquery,String alias,Transaction tx) throws Exception{
//		if(tblName == null){
//			return;
//		}
//		//TODO
//	}
	
	@Override
	public void beforeFirst() throws Exception {
		s = HeapfileInterface.getTableIterator(dbName+"."+tblName, tx);
	}

	@Override
	public void close() throws Exception {
		String tmp = tblName.substring(0,3);
		if(tmp.equals("tmp")){
			HeapfileInterface.dropTable(dbName+"."+tblName, tx);
		}
	}

	@Override
	public ResultRow getCurrent() throws Exception {
		if(tuple == null){
			return null;
		}
		if(result == null){
			result = new ResultRow();
			for(int i=1; i<=tuple.noOfFlds();i++){
				ResultSchema sch = getSchema();
				switch(sch.get(i-1).type){
					case Common.Types.INT:
					case Common.Types.BOOLEAN:
					{
						Integer intResult = tuple.getIntFld(i, tx, dbName+"."+tblName);
						result.add(intResult.toString());
						break;
					}
					case Common.Types.CHAR:
					case Common.Types.VARCHAR:
					case Common.Types.DECIMAL:
					case Common.Types.DATETIME:
					case Common.Types.TIMESTAMP:
					{
						String strResult = tuple.getStrFld(i, tx, dbName+"."+tblName);
						result.add(strResult);
						break;
					}
					case Common.Types.FLOAT:
					{
						Float floatResult = tuple.getFloFld(i, tx, dbName+"."+tblName);
						result.add(floatResult.toString());
						break;
					}
				}
				
			}
		}
		
		return result;
	}

	@Override
	public ResultSchema getSchema() throws Exception {
		return schema;
	}

	@Override
	public boolean hasField(String fldname) throws Exception{
		attrSchema[] catalog= HeapfileInterface.getTableInfo(dbName+"."+tblName, tx);
		for(int i = 0; i < catalog.length; i++){
			if(catalog[i].attrName.equals(fldname)||catalog[i].attrName.endsWith(fldname))
				return true;
		}
		return false;
	}

	@Override
	public ResultRow next() throws Exception {
		rid = new RID();
		if(flag){
			flag = false;
			return new ResultRow();
		}
		if(s == null){
			return null;
		}
		tuple = s.getNext(rid, tx, dbName+"."+tblName);
		if(tuple == null){
			return null;
		}
		HeapfileInterface.getTupleStructure(tuple, dbName+"."+tblName, schema.size(), tx);
		result = null;
		return getCurrent();
		
	}
	/**
	 * @return
	 */
	public RID getRID() {
		return rid;
	}
//	
//	/**
//	 * 
//	 * @param tuple
//	 * @param rid
//	 * @throws Exception
//	 */
//	public void SetTuple(Tuple tuple,RID rid)throws Exception{
//		schema = getSchema();
//		int fldCnt = schema.size();
//		attrNode[] attrList = new attrNode[fldCnt];
//		for(int i=0;i<fldCnt;i++){
//			switch(schema.get(i).type){
//				case Common.Types.INT:
//				case Common.Types.BOOLEAN:
//				{
//					attrList[i]=new attrNode(schema.get(i).name,tuple.getIntFld(i, tx,tblName)+"");
//					break;
//				}
//				case Common.Types.CHAR:
//				case Common.Types.VARCHAR:
//				case Common.Types.DECIMAL:
//				case Common.Types.DATETIME:
//				case Common.Types.TIMESTAMP:
//				{
//					attrList[i]=new attrNode(schema.get(i).name,tuple.getStrFld(i, tx, tblName));
//					break;
//				}
//				case Common.Types.FLOAT:
//				{
//					attrList[i]=new attrNode(schema.get(i).name,tuple.getFloFld(i, tx, tblName)+"");
//					break;
//				}
//			}
//		}
//		HeapfileInterface.updateRec(rid, dbname+"."+tblName, fldCnt, attrList, tx);
//	}
	
	private String tblName;
	private String dbName;
	private ResultRow result;
	private ResultSchema schema;
	private Transaction tx;
	private Scan scan;
	private RID rid;
	private Tuple tuple;
	private heap.Scan s;
	private boolean flag;

}
